package com.tjec.common.utils;

import com.jcraft.jsch.*;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.tjec.project.system.domain.BmsAttachmentChunk;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

@SuppressWarnings("all")
@Component
//@ConfigurationProperties(prefix = "sftp")
//@PropertySource("classpath:application.yml")
public class SFtpUtil {
    private static final Logger log = LoggerFactory.getLogger(SFtpUtil.class);
    //private ResourceBundle conf= ResourceBundle.getBundle("application.yml");

    @Value("${sftp.uploadId}")
    private String IP;
    @Value("${sftp.port}")
    private Integer PORT;//端口
    @Value("${sftp.username}")
    private String USERNAME;//用户名
    @Value("${sftp.password}")
    private String PASSWORD;//密码


    //路径
    private String PATH = "";
    private Session session = null;
    private Channel channel = null;

    public SFtpUtil() {

    }

    public SFtpUtil(String ip, String username, String password) {
        this.IP = ip;
        this.USERNAME = username;
        this.PASSWORD = password;
    }

    public SFtpUtil(String ip, int port, String username, String password) {
        this.IP = ip;
        this.PORT = port;
        this.USERNAME = username;
        this.PASSWORD = password;
    }

    /*** 连接ftp服务器* * @throws IOException */
    public boolean connectServer() throws Exception {
        JSch jsch = new JSch();
        try {
            log.debug("ip:{}", IP);
            session = jsch.getSession(this.USERNAME, this.IP, this.PORT);
            session.setPassword(this.PASSWORD);

            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config); // 为Session对象设置properties
            session.setTimeout(Integer.MAX_VALUE); // 设置timeout时间
            session.connect(); // 通过Session建立链接

            channel = session.openChannel("sftp"); // 打开SFTP通道
            channel.connect(); // 建立SFTP通道的连接
            // 用2进制上传、下载
            System.out.println("已登录到\"" + this.IP + "\"目录");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 关闭sftp连接
     *
     * @throws Exception
     */
    public void closeServer() throws Exception {
        try {
            if (channel != null) {
                channel.disconnect();
            }
            if (session != null) {
                session.disconnect();
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }

    }

    /**
     * 上传文件
     *
     * @param in          要上传的文件
     * @param newDir      新的文件存放路径
     * @param newFileName 新的文件名
     */
    public void put(InputStream in, String newDir, String newFileName) throws Exception {
        ChannelSftp chsftp = (ChannelSftp) channel;
        try {
            createPath(newDir, chsftp);
            log.debug("文件上传地址：" + newDir + newFileName);
            //chsftp.setBulkRequests(16);
            chsftp.put(in, newDir + newFileName, ChannelSftp.APPEND);
            //chsftp.quit();
            //this.closeServer();
            System.out.println(newFileName + "文件上传成功");
        } catch (Exception e) {
            this.closeServer();
            System.out.println(newFileName + "文件上传出错！");
            throw e;
        }

    }

    /**
     * 目录创建
     *
     * @param newDir
     * @param chsftp
     * @throws SftpException
     */
    private void createPath(String newDir, ChannelSftp chsftp)
            throws SftpException {
        String splitStr = newDir.indexOf("\\") == -1 ? "/" : "\\\\";
        String[] docName = newDir.substring(0, newDir.lastIndexOf(splitStr)).split(splitStr);
        String mikdir = "";
        for (int i = 1; i < docName.length - 1; i++) {
            mikdir = mikdir + splitStr + docName[i];
            log.debug("mikdir:{}",mikdir);
            Vector<LsEntry> fileNames = chsftp.ls(mikdir);
            boolean exists = true;
            for (LsEntry obj : fileNames) {
                SftpATTRS t = obj.getAttrs();
                if (t.isDir() && obj.getFilename().equals(docName[i + 1])) {//不存在文件夹，创建文件夹
                    exists = false;
                }
            }
            if (exists) {
                chsftp.cd(mikdir);
                chsftp.mkdir(mikdir + splitStr + docName[i + 1]);
                System.out.println(mikdir + splitStr + docName[i + 1] + " 目录创建成功!");
            }
        }
    }

    /**
     * 上传文件
     *
     * @param in          要上传的文件
     * @param newDir      新的文件存放路径
     * @param newFileName 新的文件名（全名）
     */
    public void put(BufferedImage img, String newDir, String newFileName) throws Exception {
        ChannelSftp chsftp = (ChannelSftp) channel;
        try {
            this.createPath(newDir, chsftp);
            InputStream in = null;
            ImageOutputStream ios = null;

            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ios = ImageIO.createImageOutputStream(os);
            ImageIO.write(img, "jpg", ios);
            in = new ByteArrayInputStream(os.toByteArray());
            chsftp.put(in, newDir + newFileName);
            chsftp.quit();
            this.closeServer();
            System.out.println("图片上传成功");
        } catch (Exception e) {
            e.printStackTrace();
            this.closeServer();
            System.out.println("图片上传出错！");
        }

    }

    /**
     * 文件合并
     *
     * @param targetFile
     * @param folder
     */
    public void merge(String targetFile, String folder, String filename) throws Exception {

        //ChannelSftp chsftp = (ChannelSftp)channel;
        try {
        	//this.connectServer();
            if (!channel.isConnected()) {
                this.connectServer();
            }
           // Thread.sleep(3000);
            ChannelSftp chsftp = (ChannelSftp) channel;
            createPath(targetFile, chsftp);
            log.debug("folder:{}",folder);
            chsftp.cd(folder);
            //去除所有文件名
            List<BmsAttachmentChunk> list = new ArrayList<>();
            BmsAttachmentChunk bmsAttachmentChunk;
            Vector<?> vector = chsftp.ls(folder);
            for (Object item : vector) {
                LsEntry entry = (LsEntry) item;
                //SftpATTRS aa = entry.getAttrs();
                String name = entry.getFilename();
                System.out.println("文件名>>>>>>>>>>>>>>>>" + name);
                if (name.indexOf("-") > 0) {
                    bmsAttachmentChunk = new BmsAttachmentChunk();
                    bmsAttachmentChunk.setFilename(name);
                    list.add(bmsAttachmentChunk);
                }

            }
            //合并文件
            list.stream().filter(a -> !a.getFilename().equals(filename))
                    .sorted((o1, o2) -> {
                        String p1 = o1.getFilename();
                        String p2 = o2.getFilename();
                        int i1 = p1.lastIndexOf("-");
                        int i2 = p2.lastIndexOf("-");
                        return Integer.valueOf(p2.substring(i2)).compareTo(Integer.valueOf(p1.substring(i1)));
                    })
                    .forEach(b -> {
                        InputStream in = null;
                        try {
                        	
                            in = chsftp.get(b.getFilename());
                            byte[] fileData = IOUtils.toByteArray(in);
                            System.out.println("数据长度：" + fileData.length);
                            InputStream sbs = new ByteArrayInputStream(fileData);
                            chsftp.put(sbs, targetFile + filename, ChannelSftp.APPEND);
                            
                            chsftp.rm(b.getFilename());
                        } catch (SftpException | IOException e) {
                            e.printStackTrace();
                        }

                    });
            log.debug("文件合并地址：" + targetFile + filename);
            //chsftp.quit();
            //this.closeServer();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 下载文件
     *
     * @param directory    下载目录
     * @param downloadFile 下载的文件
     * @param saveFile     存在本地的路径
     * @param sftp
     */
    public void download(String directory, String downloadFile, String saveFile) {
        try {
            ChannelSftp chsftp = (ChannelSftp) channel;
            chsftp.cd(directory);
            File file = new File(saveFile);
            chsftp.get(downloadFile, new FileOutputStream(file));
            this.closeServer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 下载文件
     *
     * @param directory    下载目录
     * @param downloadFile 下载的文件
     * @param sftp
     */
    public InputStream download(String directory, String downloadFile) throws Exception {
        try {
            if (!channel.isConnected()) {
                this.connectServer();
            }
            ChannelSftp chsftp = (ChannelSftp) channel;
            chsftp.cd(directory);
            InputStream in = chsftp.get(downloadFile);
			/*int count = 0;
			while (count == 0) {
				count = in.available();
			}*/
            byte[] fileData = IOUtils.toByteArray(in);
            System.out.println("数据长度：" + fileData.length);
            InputStream sbs = new ByteArrayInputStream(fileData);
            return sbs;

            //return in;

        } catch (Exception e) {
            this.closeServer();
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 删除文件
     *
     * @param directory  要删除文件所在目录
     * @param deleteFile 要删除的文件
     * @param sftp
     */
    public void delete(String directory, String deleteFile) {
        try {
            ChannelSftp sftp = (ChannelSftp) channel;
            sftp.cd(directory);
            sftp.rm(deleteFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 移动文件
     *
     * @param oldPath
     * @param newPath
     * @param newDir
     */
    public void rename(String oldPath, String newPath, String newDir) {
        try {
            ChannelSftp sftp = (ChannelSftp) channel;
            createPath(newDir, sftp);
            sftp.rename(oldPath, newPath);
            this.closeServer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        /*SFtpUtil sftpUtil = new SFtpUtil("192.168.1.245", 22, "root", "yzxx1234!!");
        boolean isconnect = sftpUtil.connectServer();
        System.out.println(isconnect ? "连接成功！" : "连接失败！");*/
//		File file = new File("D:\\photo\\cm\\S112768_JK0000000081425.jpg");
//		InputStream in = new FileInputStream(file);
//		sftpUtil.put(in, "/photo/cm11/cm/","aa.jpg");

    }
}
